#include <stdio.h>
#include <stdlib.h>
#include "TI_Command.h"
#include "TI_FS_Command.h"
#include <elasys_server.h>

#define FD_MAGIC           0x89868230L
#define DD_MAGIC           0x89868440L
#define DD_MAGIC_ROOT      0x89868441L
#define DD_MAGIC_TI_ROOT   0x89868442L

#define FLASH_ROOT "ElaDriveF"
#define TF_ROOT "ElaDriveE"
#define ROOT_NAME_LEN 9

static IBasicFileSystem *s_pI_TF_FileSystem = NULL;
static IBasicDirectory *s_pI_TF_Directory = NULL;
static IBasicFileSystem *s_pI_FLASH_FileSystem = NULL;
static IBasicDirectory *s_pI_FLASH_Directory = NULL;

typedef struct{
    IBasicFile *pIBsFile;
    Int32 offset;
    UInt32 magic;
} FD;

typedef struct{
    IBasicDirectory *pIBsDirectory;
    IWStringEnumerator *pIWStringEnumerator;
    wchar_t *wszDirName;
    int iLocation;
    UInt32 magic;
} DD;

static DD s_TIRootDD;

typedef enum _BtFsStatus
{
  BT_STATUS_HAL_FS_SUCCESS =                              0,
  BT_STATUS_HAL_FS_PENDING =                              1,
  BT_STATUS_HAL_FS_ERROR_GENERAL =                        -1,
  BT_STATUS_HAL_FS_ERROR_NODEVICE =                       -2,
  BT_STATUS_HAL_FS_ERROR_FS_CORRUPTED =                   -3,
  BT_STATUS_HAL_FS_ERROR_NOT_FORMATTED =                  -4,
  BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE =                   -5,
  BT_STATUS_HAL_FS_ERROR_FSFULL =                         -6,
  BT_STATUS_HAL_FS_ERROR_BADNAME =                        -7,
  BT_STATUS_HAL_FS_ERROR_NOTFOUND =                       -8,
  BT_STATUS_HAL_FS_ERROR_EXISTS =                         -9,
  BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED  =                 -10,
  BT_STATUS_HAL_FS_ERROR_NAMETOOLONG =                    -11,
  BT_STATUS_HAL_FS_ERROR_INVALID =                        -12,
  BT_STATUS_HAL_FS_ERROR_DIRNOTEMPTY =                    -13,
  BT_STATUS_HAL_FS_ERROR_FILETOOBIG =                     -14,
  BT_STATUS_HAL_FS_ERROR_NOTAFILE =                       -15,
  BT_STATUS_HAL_FS_ERROR_NUMFD =                          -16,
  BT_STATUS_HAL_FS_ERROR_BADFD =                          -17,
  BT_STATUS_HAL_FS_ERROR_LOCKED =                         -18,
  BT_STATUS_HAL_FS_ERROR_NOT_IMPLEMENTED =                -19,
  BT_STATUS_HAL_FS_ERROR_NOT_INITIALIZED =                -20,
  BT_STATUS_HAL_FS_ERROR_EOF =                            -21,
  BT_STATUS_HAL_FS_ERROR_FILE_NOT_CLOSE =                 -22,
  BT_STATUS_HAL_FS_ERROR_READING_FILE =                   -23,
  BT_STATUS_HAL_FS_ERROR_OPENING_FILE =                   -24,
  BT_STATUS_HAL_FS_ERROR_WRITING_TO_FILE =                -25,
  BT_STATUS_HAL_FS_ERROR_MAX_FILE_HANDLE =                -26,
  BT_STATUS_HAL_FS_ERROR_MAKE_DIR =                       -27,
  BT_STATUS_HAL_FS_ERROR_REMOVE_DIR =                     -28,
  BT_STATUS_HAL_FS_ERROR_MAX_DIRECTORY_HANDLE =           -29,
  BT_STATUS_HAL_FS_ERROR_INVALID_DIRECTORY_HANDLE_VALUE = -30,
  BT_STATUS_HAL_FS_ERROR_DIRECTORY_NOT_EMPTY =            -31,
  BT_STATUS_HAL_FS_ERROR_FILE_HANDLE =                    -32,
  BT_STATUS_HAL_FS_ERROR_FIND_NEXT_FILE =                 -33,
  BT_STATUS_HAL_FS_ERROR_OPEN_FLAG_NOT_SUPPORT=           -34,
  BT_STATUS_HAL_FS_ERROR_DIRECTORY_HANDLE_OUT_OF_RANGE =  -35
} BtFsStatus;

ELAPI _CProfile_GetInt32(
    /* [in] */ AString appName,
    /* [in] */ AString keyName,
    /* [out] */ Int32 *pValue);

ELAPI _CProfile_GetAString(
    /* [in] */ AString appName,
    /* [in] */ AString keyName,
    /* [out] */ AStringBuf *pReturnedString);

EXTERN_C int CDECL _sprintf(char *buf, const char *fmt,...);

static Boolean utf8ToUnicode(const char* src, wchar_t *wstr)
{
    if (src == NULL && wstr == NULL) {
        return FALSE;
    }

    Boolean flag = TRUE;

    int size_s = strlen(src);
    int size_d = size_s + 1;

    wchar_t *des = new wchar_t[size_d];
    memset(des, 0, size_d * sizeof(wchar_t));

    int s = 0, d = 0;
    while (s < size_s && d < size_d) {
        unsigned char c = src[s];
        if ((c & 0x80) == 0) {
            des[d++] += src[s++];
        }
        else if((c & 0xE0) == 0xC0) {///< 110x-xxxx 10xx-xxxx
            wchar_t &wideChar = des[d++];

            wideChar  = (src[s + 0] & 0x3F) << 6;
            wideChar |= (src[s + 1] & 0x3F);

            s += 2;
        }
        else if((c & 0xF0) == 0xE0) { ///< 1110-xxxx 10xx-xxxx 10xx-xxxx
            wchar_t &wideChar = des[d++];

            wideChar  = (src[s + 0] & 0x1F) << 12;
            wideChar |= (src[s + 1] & 0x3F) << 6;
            wideChar |= (src[s + 2] & 0x3F);

            s += 3;
        }
        else {
            flag = FALSE;
            break;
        }
    }

    des[d] = L'\0';

    wcscpy(wstr,des);
    delete[] des;
    des = NULL;

    return flag;
}

static Boolean UnicodeToutf8(const wchar_t *wchar, char *utf8)
{
    if (!wchar || !utf8) return FALSE;

    int len = 0;

    while (*wchar) {
        wchar_t wc = *wchar;
        if (wc < 0x80) {
            utf8[len++] = (char)wc;
        }
        else if(wc < 0x800) {
            utf8[len++] = 0xc0 | (wc >> 6);
            utf8[len++] = 0x80 | (wc & 0x3f);
        }
        else {
            utf8[len++] = 0xe0 | (wc >> 12);
            utf8[len++] = 0x80 | ((wc >> 6) & 0x3f);
            utf8[len++] = 0x80 | (wc & 0x3f);
        }

        wchar++;
    }
    utf8[len] = '\0';
    return TRUE;
}



/*iLocation==0: local flash;*/
/*iLocation==1: remote TF;*/
ECode FindRootName(wchar_t *pRootDirName, int iLocation)
{
    ECode ec = E_INVALID_ARGUMENT;
    Int32 ulDiskNum;
    int i = 0;
    char szDisk[10];
    AStringBuf_<32> asDiskType;
    AStringBuf_<_MAX_PATH> asServiceName;
    char DiskTypeName[20];

    ec = _CProfile_GetInt32("Info", "DiskNum", &ulDiskNum);
    if (FAILED(ec)) {
        kprintf("Can't find '[Info] DiskNum=' in elastos.cfg.\n");
        return ec;
    }

    if(0 == iLocation){
        strcpy(DiskTypeName, "FlashDisk");
    }else {
        strcpy(DiskTypeName, "Removable");
    }

    for (i = ulDiskNum; i > 0; i--) {
        _sprintf((char *)szDisk, "Disk%d",  i);
        kprintf("FindRootName disk name :%s.\n", szDisk);
        ec = _CProfile_GetAString(szDisk, "DiskType", &asDiskType);
        if (FAILED(ec)) {
            kprintf("ERROR: Can't find '[Disk%d] in elastos.cfg.\n", i);
            return ec;
        }

        if(0 == strcmp(DiskTypeName, asDiskType)){
            ec = _CProfile_GetAString(szDisk, "ServiceName", &asServiceName);
            if (FAILED(ec)) {
                kprintf("ERROR: Can't find '[Disk%d] ServiceName=' in elastos.cfg.\n", i);
                return ec;
            }
            kprintf("FindRootName ServiceName :%s.\n", (char *)asServiceName);
            _strtowcs(pRootDirName, asServiceName);
            return NOERROR;
        }
    }

    return ec;
}

ECode InitRoot(wchar_t *pRootDirName, int iLocation)
{
    IBasicFileSystem *pIBsFileSystem = NULL;
    IBasicDirectory *pIBsDirectory = NULL;
    ECode ec = NOERROR;

    ec = DzFindService(pRootDirName, (PInterface *)&pIBsFileSystem);
    if (FAILED(ec)) {
        kprintf("Failed GetRootDirs DzFindService ec:0x%x\n", ec);
        return ec;
    }

    // GetRoot
    ec = pIBsFileSystem->GetRoot(&pIBsDirectory);
    if (FAILED(ec)) {
        kprintf("Failed GetRootDirs GetRoot! ec:0x%x\n", ec);
        pIBsFileSystem->Release();
        return ec;
    }

    if(0 == iLocation){
        s_pI_FLASH_FileSystem = pIBsFileSystem;
        s_pI_FLASH_Directory = pIBsDirectory;
    }else {
        s_pI_TF_FileSystem = pIBsFileSystem;
        s_pI_TF_Directory = pIBsDirectory;
    }

    return ec;
}

ECode ReInitFlash()
{
    wchar_t wszRootDirName[20];
    ECode ec = FindRootName(wszRootDirName, 0);
    if(FAILED(ec)){
        return ec;
    }
    kprintf("ReInitFlash Get wszRootDirName:%S.\n", wszRootDirName);
    ec = InitRoot(wszRootDirName, 0);
    if(FAILED(ec)){
        return ec;
    }
    return NOERROR;
}

ECode ReInitTF()
{
    wchar_t wszRootDirName[20];
    ECode ec = FindRootName(wszRootDirName, 1);
    if(FAILED(ec)){
        return ec;
    }
    kprintf("ReInitTF Get wszRootDirName:%S.\n", wszRootDirName);
    ec = InitRoot(wszRootDirName, 1);
    if(FAILED(ec)){
        return ec;
    }
    return NOERROR;
}

ECode ReInit_BT_FS()
{
    ECode ec = ReInitFlash();
    if(FAILED(ec)){
        return ec;
    }
    ec = ReInitTF();
    if(FAILED(ec)){
        return ec;
    }
    return NOERROR;
}

char *GetRoot(char* fullPathFileName,
    IBasicDirectory **ppOutIBsDirectory,
    IBasicFileSystem **ppOutIBsFileSystem,
    int *piLocation)
{
    char *p = fullPathFileName;
    IBasicFileSystem *pIBsFileSystem = NULL;
    IBasicDirectory *pIBsDirectory = NULL;

    if((NULL == s_pI_FLASH_FileSystem)
     ||(NULL == s_pI_FLASH_Directory)){
        kprintf("Filesys not init, fullPathFileName:%s.\n",
            fullPathFileName);
        return NULL;
    }

    if(0 == strncmp(FLASH_ROOT, fullPathFileName, ROOT_NAME_LEN)){
        pIBsFileSystem = s_pI_FLASH_FileSystem;
        pIBsDirectory = s_pI_FLASH_Directory;
        p += ROOT_NAME_LEN;
        if('\0' != *p)p++;//Not root dir.
        if(NULL != piLocation)*piLocation = 0;
//        kprintf("########FLASH_ROOT, fullPathFileName:%s.********\n",
//            fullPathFileName);
    } else if(0 == strncmp(TF_ROOT, fullPathFileName, ROOT_NAME_LEN)){
        if((NULL == s_pI_TF_FileSystem)
        ||(NULL == s_pI_TF_Directory)){
            ECode ec = ReInitTF();
            if(FAILED(ec)){
                return NULL;
            }
        }
        pIBsFileSystem = s_pI_TF_FileSystem;
        pIBsDirectory = s_pI_TF_Directory;
        p += ROOT_NAME_LEN;
        if('\0' != *p)p++;//Not root dir.
        if(NULL != piLocation)*piLocation = 1;
//        kprintf("########TF_ROOT, fullPathFileName:%s.********\n",
//            fullPathFileName);
    } else {
        //Not Elastos file
        kprintf("Filesys can not acesse default root, fullPathFileName:%s.\n",
            fullPathFileName);
        return NULL;
    }
//    kprintf("########GetRoot, OutPathFileName:%s.********\n", p);

    if(NULL != ppOutIBsFileSystem){
        *ppOutIBsFileSystem = pIBsFileSystem;
    }

    if(NULL != ppOutIBsDirectory){
        *ppOutIBsDirectory = pIBsDirectory;
    }

    return p;
}

int TICommandFsInit()
{
    ECode ec;
    wchar_t wszRootDirName[20];
    int i;

    for(i = 0; i<2; i++){
        ec = FindRootName(wszRootDirName, i);
        if(FAILED(ec)){
            goto ERR;
        }
        kprintf("Get wszRootDirName:%S.\n", wszRootDirName);
        ec = InitRoot(wszRootDirName, i);
        if(FAILED(ec)&&(1!=i)){//Except TF card
            goto ERR;
        }
    }

    s_TIRootDD.magic = DD_MAGIC_TI_ROOT;

    return BT_STATUS_HAL_FS_SUCCESS;

ERR:
    TICommandFsDeInit();
    return BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
}


int TICommandFsDeInit()
{
    if(NULL != s_pI_TF_Directory){
        s_pI_TF_Directory->Release();
        s_pI_TF_Directory = NULL;
    }

    if(NULL != s_pI_TF_FileSystem){
        s_pI_TF_FileSystem->Release();
        s_pI_TF_FileSystem = NULL;
    }

    if(NULL != s_pI_FLASH_Directory){
        s_pI_FLASH_Directory->Release();
        s_pI_FLASH_Directory = NULL;
    }

    if(NULL != s_pI_FLASH_FileSystem){
        s_pI_FLASH_FileSystem->Release();
        s_pI_FLASH_FileSystem = NULL;
    }

    kprintf("*****TICommandFsDeInit OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;
}



int TICommandFsOpen(char* szInFullPathFileName, int flags, int *pfd)
{
    ECode ec;
    FileAccessMode ac = 0;
    int ret = BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
    FD *pFd = NULL;
    Boolean bExclusive = FALSE;
    char* fullPathFileName;
    IBasicDirectory *pIBsDirectory = NULL;

    if((0 == flags)
        ||(NULL == szInFullPathFileName)
        ||(_MAX_PATH <= strlen(szInFullPathFileName))
        ||('\0' == szInFullPathFileName[0]))
    {
        kprintf("TICommandFsOpen invalid argument\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID;
    }

    fullPathFileName = GetRoot(szInFullPathFileName,
        &pIBsDirectory,
        NULL,
        NULL);
    if(NULL == fullPathFileName){
        return BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
    }

    wchar_t *wszFullPath = (wchar_t *)malloc((_MAX_PATH+1)*2);
    if(NULL == wszFullPath){
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }

    pFd = (FD *)malloc(sizeof(FD));
    if(NULL == pFd){
        kprintf("Failed TICommandFsOpen malloc\n");
        free(wszFullPath);
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }
    memset(pFd, 0, sizeof(FD));
    pFd->magic  = FD_MAGIC;

    if (!utf8ToUnicode(fullPathFileName,wszFullPath))
    {
        goto ERR;
    }

    if((BT_FS_O_EXCL & flags)&&(BT_FS_O_CREATE  & flags)){
        bExclusive = TRUE;
    }

    if(BT_FS_O_WRONLY & flags){
        ac |= FileAccessMode_Write;
    }

    if(BT_FS_O_RDONLY & flags){
        ac |= FileAccessMode_Read;
    }

    if(BT_FS_O_RDWR & flags){
        ac |= FileAccessMode_ReadWrite;
    }

    ec = pIBsDirectory->CreateFile(wszFullPath, ac, bExclusive, &pFd->pIBsFile);
    if (FAILED(ec)) {
        kprintf("FAILED TICommandFsOpen CreateFile! ec = 0x%x, ac:0x%x, bExclusive:%d.\n",
        ec, ac, bExclusive);
        if(E_INVALID_ARGUMENT == ec){
            ret = BT_STATUS_HAL_FS_ERROR_INVALID;
        } else if(E_FS_FILE_EXISTS == ec) {
            ret = BT_STATUS_HAL_FS_ERROR_EXISTS;
        } else if(E_FS_IS_DIRECTORY == ec){
            ret = BT_STATUS_HAL_FS_ERROR_NOTAFILE;
        } else if(E_FS_NO_PERMISSION == ec){
            ret = BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
        } else {
            ret = BT_STATUS_HAL_FS_ERROR_OPENING_FILE;
        }
        goto ERR;
    }

    //exclusive attribute
//    ec = pFd->pIBsFile->SetShareMode(FileShareMode_Deny);
//    if (FAILED(ec)) {
//        ret = BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
//        goto ERR;
//    }

    if(BT_FS_O_TRUNC & flags){
        IAbsoluteIO *iAb = NULL;
        iAb = IAbsoluteIO::Probe(pFd->pIBsFile);
        if (NULL == iAb) {
            kprintf("FAILED TICommandFsOpen Probe!\n");
            ret = BT_STATUS_HAL_FS_ERROR_OPENING_FILE;
            goto ERR;
        }
        ec = iAb->SetSize(0);
        if (FAILED(ec)) {
            kprintf("FAILED TICommandFsOpen SetSize! ec = 0x%08x\n", ec);
            if(E_FS_NO_PERMISSION == ec){
                ret = BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
            } else if(E_FS_NO_SPACE == ec) {
                ret = BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
            } else if(E_FS_FILE_BUSY == ec) {
                ret = BT_STATUS_HAL_FS_PENDING;
            } else {
                ret = BT_STATUS_HAL_FS_ERROR_OPENING_FILE;
            }
            goto ERR;
        }
        pFd->offset = 0;
    } else if(BT_FS_O_APPEND & flags) {
        IAbsoluteIO *iAb = NULL;
        Int32 Size;
        iAb = IAbsoluteIO::Probe(pFd->pIBsFile);
        if (NULL == iAb) {
            kprintf("FAILED TICommandFsOpen Probe!\n");
            ret = BT_STATUS_HAL_FS_ERROR_OPENING_FILE;
            goto ERR;
        }
        ec = iAb->GetSize(&Size);
        if (FAILED(ec)) {
            kprintf("FAILED TICommandFsOpen GetSize! ec = 0x%08x\n", ec);
            if(E_INVALID_ARGUMENT == ec){
                ret = BT_STATUS_HAL_FS_ERROR_INVALID;
             } else {
                ret = BT_STATUS_HAL_FS_ERROR_OPENING_FILE;
            }
            goto ERR;
        }
        pFd->offset = Size;
    }

    *pfd = (int)pFd;
    if(NULL != wszFullPath)free(wszFullPath);
    kprintf("*****TICommandFsOpen OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;

ERR:
    if(NULL != pFd->pIBsFile){
        pFd->pIBsFile->Release();
    }
    free(pFd);
    if(NULL != wszFullPath)free(wszFullPath);
    return ret;

}

int TICommandFsClose( int fd )
{
    FD *pFd = (FD *)fd;
    if(FD_MAGIC != pFd->magic){
        kprintf("Invalid fd\n");
        return BT_STATUS_HAL_FS_ERROR_BADFD;
    }

    if(NULL != pFd->pIBsFile){
        pFd->pIBsFile->Sync();
        pFd->pIBsFile->Release();
    }

    free(pFd);

    kprintf("*****TICommandFsClose OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;
}

int TICommandFsRead ( int fd, void* buf, unsigned int nSize, unsigned int *pnReadedSize)
{
    FD *pFd = (FD *)fd;
    int ret;
    if(FD_MAGIC != pFd->magic){
        kprintf("Invalid fd\n");
        return BT_STATUS_HAL_FS_ERROR_BADFD;
    }

    if(NULL == buf){
        kprintf("Invalid argument\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID;
    }
    if(0 == nSize){
    kprintf("*****TICommandFsRead OK*****\n");
        return BT_STATUS_HAL_FS_SUCCESS;
    }


    ECode ec;
    IAbsoluteIO *iAb = NULL;
    MemoryBuf *pmbbuf = MemoryBuf::Alloc((Int32)nSize);
    if(NULL == pmbbuf){
        kprintf("TICommandFsRead not enough memory.\n");
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }
    int readedSize;
    iAb = IAbsoluteIO::Probe(pFd->pIBsFile);
    if (NULL == iAb) {
        kprintf("FAILED TICommandFsRead Probe!\n");
        ret = BT_STATUS_HAL_FS_ERROR_READING_FILE;
        goto ERR;
    }
    ec = iAb->Read(pFd->offset, (Int32)nSize, pmbbuf);
    if (FAILED(ec)) {
        kprintf("FAILED TICommandFsRead Read! ec = 0x%08x\n", ec);
        if(E_INVALID_ARGUMENT == ec){
            ret = BT_STATUS_HAL_FS_ERROR_INVALID;
        } else if(E_FS_FILE_BUSY == ec) {
            ret = BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
        } else {
            ret = BT_STATUS_HAL_FS_ERROR_READING_FILE;
        }
        goto ERR;
    }
    readedSize = pmbbuf->GetUsed();
    pFd->offset += readedSize;
    memcpy(buf, (void *)pmbbuf->GetPayload(), readedSize);
    if(NULL != pnReadedSize)*pnReadedSize = readedSize;
    MemoryBuf::Free(pmbbuf);
    kprintf("*****TICommandFsRead OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;

ERR:
    MemoryBuf::Free(pmbbuf);
    return ret;

}

int TICommandFsWrite( int fd, void* buf, unsigned int nSize, unsigned int *pnWritedSize)
{
    FD *pFd = (FD *)fd;
    int ret;
    if(FD_MAGIC != pFd->magic){
        kprintf("Invalid fd\n");
        return BT_STATUS_HAL_FS_ERROR_BADFD;
    }

    if(NULL == buf){
        kprintf("Invalid argument\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID;
    }
    if(0 == nSize){
        return BT_STATUS_HAL_FS_SUCCESS;
    }

    ECode ec;
    IAbsoluteIO *iAb = NULL;
    Int32 iWriteSize;
    MemoryBuf *pmbbuf = MemoryBuf::Alloc((Byte *)buf, (Int32)nSize);
    if(NULL == pmbbuf){
        kprintf("TICommandFsWrite not enough memory.\n");
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }
    iAb = IAbsoluteIO::Probe(pFd->pIBsFile);
    if (NULL == iAb) {
        kprintf("FAILED TICommandFsWrite Probe!\n");
        ret = BT_STATUS_HAL_FS_ERROR_WRITING_TO_FILE;
        goto ERR;
    }

    kprintf("*********TICommandFsWrite pFd->offset:%x.nSize0x%x.*********\n", pFd->offset, nSize);
    ec = iAb->Write(pFd->offset, *pmbbuf, &iWriteSize);
    if (FAILED(ec)) {
        kprintf("FAILED TICommandFsWrite Write! ec = 0x%08x\n", ec);
        if(E_INVALID_ARGUMENT == ec){
            ret = BT_STATUS_HAL_FS_ERROR_INVALID;
        } else if(E_FS_NO_PERMISSION == ec) {
            ret = BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
        } else if(E_FS_NO_SPACE == ec){
            ret = BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
        } else {
            ret = BT_STATUS_HAL_FS_ERROR_WRITING_TO_FILE;
        }
        goto ERR;
    }
    pFd->offset += iWriteSize;
    if(NULL != pnWritedSize)*pnWritedSize = iWriteSize;
    MemoryBuf::Free(pmbbuf);
    kprintf("*****TICommandFsWrite OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;

ERR:
    MemoryBuf::Free(pmbbuf);
    return ret;
}

int TICommandFsFlush( int fd )
{
    FD *pFd = (FD *)fd;
    if(FD_MAGIC != pFd->magic){
        kprintf("Invalid fd\n");
        return BT_STATUS_HAL_FS_ERROR_BADFD;
    }

    ECode ec = pFd->pIBsFile->Sync();
    if (FAILED(ec)) {
        kprintf("FAILED TICommandFsFlush! ec = 0x%08x\n", ec);
        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }

    kprintf("*****TICommandFsFlush OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;
}

int TICommandFsRemove( char *szInFullPathFileName )
{
    char* fullPathFileName;
    IBasicDirectory *pIBsDirectory = NULL;

    if((NULL == szInFullPathFileName)
        ||(_MAX_PATH <= strlen(szInFullPathFileName))
        ||('\0' == szInFullPathFileName[0]))
    {
        kprintf("TICommandFsRemove invalid argument\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID;
    }

    fullPathFileName = GetRoot(szInFullPathFileName,
        &pIBsDirectory,
        NULL,
        NULL);
    if(NULL == fullPathFileName){
        return BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
    }

    wchar_t *wszFullPath = (wchar_t *)malloc((_MAX_PATH+1)*2);
    if(NULL == wszFullPath){
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }

    if (!utf8ToUnicode(fullPathFileName,wszFullPath))
    {
        if(NULL != wszFullPath)
        {
            free(wszFullPath);
        }

        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }

    ECode ec = pIBsDirectory->DeleteFile(wszFullPath);
    if(NULL != wszFullPath)free(wszFullPath);
    if(FAILED(ec)){
        kprintf("FAILED TICommandFsRemove DeleteFile.ec = 0x%08x\n", ec);
        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }

    kprintf("*****TICommandFsRemove OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;
}

//
//typedef enum _BtFsType
//{
//  BTHAL_FS_FILE,
//  BTHAL_FS_DIR
//} BtFsType;

//typedef struct _BTFsStat
//{
//  BtFsType         type;              /* file / dir */
//  unsigned long    size;              /* in bytes */
//  FileAccessMode   access;        /* whether read-only file */
//  int              mTime;             /* modified time */
//  int              aTime;             /* accessed time */
//  int              cTime;             /* creation time */
//} BTFsStat;
void TIFsRootStat(BTFsStat* pFileStat)
{
    pFileStat->type = (BtFsType)1;
    pFileStat->size = 0;
    pFileStat->access = (FileAccessMode)0;
    pFileStat->mTime = 0;
    pFileStat->aTime = 0;
    pFileStat->cTime = 0;

    kprintf("TIFsRootStat OK\n");
}

int TICommandFsStat( char* szInfullPathName, BTFsStat* pFileStat )
{
    int ret;
    kprintf("********TICommandFsStat****fullPathName:%s****\n", szInfullPathName);

    char* fullPathName;
    IBasicDirectory *pIBsDirectory = NULL;

    if((NULL == szInfullPathName)
        ||(_MAX_PATH <= strlen(szInfullPathName))
        ||(NULL == pFileStat))
    {
        kprintf("TICommandFsStat invalid argument\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID;
    }

    if('\0' == szInfullPathName[0]){
        TIFsRootStat(pFileStat);
        return BT_STATUS_HAL_FS_SUCCESS;
    }

    fullPathName = GetRoot(szInfullPathName,
        &pIBsDirectory,
        NULL,
        NULL);
    if(NULL == fullPathName){
        return BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
    }

    IBasicFile *pIBsFile;
    IAbsoluteIO *iAb = NULL;
    ECode ec;
    if('\0' == fullPathName[0]){
        //Root dir
        pIBsFile = IBasicFile::Probe(pIBsDirectory);
        if (NULL == pIBsFile) {
            kprintf("FAILED TICommandFsStat root Probe!\n");
            ret = BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
            goto ERR;
        }
    } else {
        wchar_t *wszFullPath = (wchar_t *)malloc((_MAX_PATH+1)*2);
        if(NULL == wszFullPath){
            return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
        }

        if (!utf8ToUnicode(fullPathName,wszFullPath))
        {
            if(NULL != wszFullPath)
            {
                free(wszFullPath);
            }

            return BT_STATUS_HAL_FS_ERROR_GENERAL;
        }

        ec = pIBsDirectory->Lookup(wszFullPath, &pIBsFile);
        if(NULL != wszFullPath)free(wszFullPath);
        if(FAILED(ec)){
            kprintf("FAILED TICommandFsStat Lookup.ec = 0x%08x\n", ec);
            return BT_STATUS_HAL_FS_ERROR_GENERAL;
        }
    }

//  BtFsType         type;              /* file / dir */
    FileType fType;
    ec = pIBsFile->GetType(&fType);
    if(FAILED(ec)){
        kprintf("FAILED TICommandFsStat GetType!ec = 0x%08x\n", ec);
        ret = BT_STATUS_HAL_FS_ERROR_INVALID;
        goto ERR;
    }
    pFileStat->type = (BtFsType)fType;

//  unsigned long    size;              /* in bytes */
    if(BT_FS_DIR == fType) {
        pFileStat->size = 0;
    } else {
        iAb = IAbsoluteIO::Probe(pIBsFile);
        if (NULL == iAb) {
            kprintf("FAILED TICommandFsStat Probe!\n");
            ret = BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
            goto ERR;
        }
        ec = iAb->GetSize((Int32 *)&pFileStat->size);
        if (FAILED(ec)) {
            kprintf("FAILED TICommandFsStat GetSize! ec = 0x%08x\n", ec);
            ret = BT_STATUS_HAL_FS_ERROR_INVALID;
            goto ERR;
        }
        iAb = NULL;
    }

//    FileAccessMode access;
    ec = pIBsFile->GetAccessMode(&pFileStat->access);
    if (FAILED(ec)) {
        if(E_INVALID_ARGUMENT == ec){
            ret = BT_STATUS_HAL_FS_ERROR_INVALID;
        } else {
            ret = BT_STATUS_HAL_FS_ERROR_GENERAL;
        }
        kprintf("FAILED TICommandFsStat GetAccessMode! ec = 0x%08x\n", ec);
        goto ERR;
    }
//  int              mTime;             /* modified time */
//  int              aTime;             /* accessed time */
//  int              cTime;             /* creation time */
    //TODO:Not implement;
    pFileStat->mTime = 0;
    pFileStat->aTime = 0;
    pFileStat->cTime = 0;

    if('\0' != fullPathName[0]){
        pIBsFile->Release();
    }
    kprintf("*****TICommandFsStat OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;
ERR:
    if('\0' != fullPathName[0]){
        if(NULL != pIBsFile)pIBsFile->Release();
    }
    return ret;
}

int TICommandFsTell( int fd, unsigned int *curPosition )
{
    FD *pFd = (FD *)fd;
    if(FD_MAGIC != pFd->magic){
        kprintf("Invalid fd\n");
        return BT_STATUS_HAL_FS_ERROR_BADFD;
    }

    *curPosition = (unsigned int)pFd->offset;

    kprintf("*****TICommandFsTell OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;
}

//typedef enum _BtFsSeekOrigin
//{
//  BT_FS_CUR,  /* from current position */
//  BT_FS_END,  /* from end of file */
//  BT_FS_START /* from start of file */
//} BtFsSeekOrigin;

int TICommandFsSeek( int fd, int offset, BtFsSeekOrigin from )
{
    FD *pFd = (FD *)fd;
    if(FD_MAGIC != pFd->magic){
        kprintf("Invalid fd\n");
        return BT_STATUS_HAL_FS_ERROR_BADFD;
    }

    if(BT_FS_START == from){
        pFd->offset = offset;
    } else if(BT_FS_CUR == from){
        pFd->offset += offset;
    } else {
        IAbsoluteIO *iAb = NULL;
        Int32 Size;
        iAb = IAbsoluteIO::Probe(pFd->pIBsFile);
        if (NULL == iAb) {
            kprintf("FAILED TICommandFsOpen Probe!\n");
            return BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
        }
        ECode ec = iAb->GetSize(&Size);
        if (FAILED(ec)) {
            kprintf("FAILED TICommandFsOpen GetSize! ec = 0x%08x\n", ec);
            return BT_STATUS_HAL_FS_ERROR_INVALID;
        }
        pFd->offset = Size;
        pFd->offset += offset;
    }

    kprintf("*****TICommandFsSeek OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;
}

int TICommandFsMkdir( char *szIndirFullPathName )
{
    char* dirFullPathName;
    IBasicDirectory *pIBsDirectory = NULL;

    if((NULL == szIndirFullPathName)
        ||(_MAX_PATH <= strlen(szIndirFullPathName))
        ||('\0' == szIndirFullPathName[0]))
    {
        kprintf("TICommandFsMkdir invalid argument\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID;
    }

    dirFullPathName = GetRoot(szIndirFullPathName,
        &pIBsDirectory,
        NULL,
        NULL);
    if(NULL == dirFullPathName){
        return BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
    }

    wchar_t *wszFullPath = (wchar_t *)malloc((_MAX_PATH+1)*2);
    if(NULL == wszFullPath){
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }

    if (!utf8ToUnicode(dirFullPathName,wszFullPath))
    {
        if(NULL != wszFullPath)
        {
            free(wszFullPath);
        }

        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }

    ECode ec = pIBsDirectory->CreateDirectory (wszFullPath, FileAccessMode_ReadWrite);
    if(NULL != wszFullPath)free(wszFullPath);
    if(FAILED(ec)){
        kprintf("FAILED TICommandFsMkdir CreateDirectory.ec = 0x%08x\n", ec);
        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }

    kprintf("*****TICommandFsMkdir OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;
}

int TICommandFsRmdir( char *szIndirFullPathName )
{
    char* dirFullPathName;
    IBasicDirectory *pIBsDirectory = NULL;

    if((NULL == szIndirFullPathName)
        ||(_MAX_PATH <= strlen(szIndirFullPathName))
        ||('\0' == szIndirFullPathName[0]))
    {
        kprintf("TICommandFsRmdir invalid argument\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID;
    }

    dirFullPathName = GetRoot(szIndirFullPathName,
        &pIBsDirectory,
        NULL,
        NULL);
    if(NULL == dirFullPathName){
        return BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
    }

    wchar_t *wszFullPath = (wchar_t *)malloc((_MAX_PATH+1)*2);
    if(NULL == wszFullPath){
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }
    if (!utf8ToUnicode(dirFullPathName,wszFullPath))
    {
        if(NULL != wszFullPath)
        {
            free(wszFullPath);
        }

        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }


    ECode ec = pIBsDirectory->DeleteDirectory(wszFullPath);
    if(NULL != wszFullPath)free(wszFullPath);
    if(FAILED(ec)){
        kprintf("FAILED TICommandFsRmdir DeleteDirectory .ec = 0x%08x\n", ec);
        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }

    kprintf("*****TICommandFsRmdir OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;
}

void TIFsOpenRootDir(int *dirDesc)
{
    *dirDesc = (int)&s_TIRootDD;
    kprintf("TIFsOpenRootDir OK\n");
}

int TICommandFsOpenDir( char *szIndirFullPathName, int *dirDesc )
{
    int ret = 0;

    char* dirFullPathName;
    int iLocation;
    IBasicDirectory *pIBsDirectory = NULL;

    if((NULL == szIndirFullPathName)
        ||(_MAX_PATH <= strlen(szIndirFullPathName))
        ||(NULL == dirDesc))
    {
        kprintf("TICommandFsOpenDir invalid argument\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID;
    }

    if('\0' == szIndirFullPathName[0]){
        TIFsOpenRootDir(dirDesc);
        return BT_STATUS_HAL_FS_SUCCESS;
    }

    dirFullPathName = GetRoot(szIndirFullPathName,
        &pIBsDirectory,
        NULL,
        &iLocation);
    if(NULL == dirFullPathName){
        return BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
    }

    wchar_t *wszFullPath = (wchar_t *)malloc((_MAX_PATH+1)*2);
    if(NULL == wszFullPath){
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }

    if (!utf8ToUnicode(dirFullPathName,wszFullPath))
    {
        if(NULL != wszFullPath)
        {
            free(wszFullPath);
        }

        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }

    DD *pDd = NULL;
    pDd = (DD *)malloc(sizeof(DD));
    if(NULL == pDd){
        kprintf("FAILED TICommandFsOpenDir malloc.\n");
        if(NULL != wszFullPath)free(wszFullPath);
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }
    memset(pDd, 0, sizeof(DD));
    pDd->pIWStringEnumerator = NULL;
    pDd->pIBsDirectory = NULL;
    pDd->magic = DD_MAGIC;
    pDd->iLocation = iLocation;
    IBasicFile *pBsf;
    if('\0' == dirFullPathName[0]){
        //root;
        pDd->pIBsDirectory = pIBsDirectory;
        *dirDesc = (int)pDd;
        pDd->magic = DD_MAGIC_ROOT;
        pDd->wszDirName = NULL;
    kprintf("*****TICommandFsOpenDir OK*****\n");
        return BT_STATUS_HAL_FS_SUCCESS;
    }
	//Cut the end path "/"
    wszFullPath[wcslen(wszFullPath)-1] = L'\0';

    ECode ec = pIBsDirectory->Lookup(wszFullPath, &pBsf);
    if(FAILED(ec)){
        kprintf("FAILED TICommandFsOpenDir Lookup.ec = 0x%08x\n", ec);
        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }

    FileType fType;
    ec = pBsf->GetType(&fType);
    if(FAILED(ec)){
        kprintf("FAILED TICommandFsOpenDir GetType!ec = 0x%08x\n", ec);
        ret = BT_STATUS_HAL_FS_ERROR_INVALID;
        goto ERR;
    }

    if(FileType_Directory == fType){
        pDd->pIBsDirectory = IBasicDirectory::Probe(pBsf);
        pDd->wszDirName =(wchar_t *)malloc((wcslen(wszFullPath) +1)*sizeof(wchar_t));
        if(NULL == pDd->wszDirName){
            kprintf("FAILED TICommandFsOpenDir malloc wszDirName.\n");
            goto ERR;
        }
        wcscpy(pDd->wszDirName, wszFullPath);
        *dirDesc = (int)pDd;
        kprintf("*****TICommandFsOpenDir OK*****\n");
        return BT_STATUS_HAL_FS_SUCCESS;
    }

ERR:
    if(NULL != pBsf)pBsf->Release();
    if(NULL !=  pDd)free(pDd);
    if(NULL != wszFullPath)free(wszFullPath);
    return ret;
}

EXTERN_C int CDECL _sprintf(char *buf, const char *fmt,...);

int TIFsRootReadNextDir(char *pOutFileName)
{
    static int i = 0;
    if(0 == i){
        strcpy(pOutFileName, FLASH_ROOT);
    } else if(1 == i) {
        if((NULL == s_pI_TF_FileSystem)
        ||(NULL == s_pI_TF_Directory)){
            ECode ec = ReInitTF();
            if(FAILED(ec)){
                goto END;
            }
        }
        strcpy(pOutFileName, TF_ROOT);
    } else {
        goto END;
    }
    i++;
    kprintf("********TIFsRootReadNextDir****pOutFileName:%s****\n", pOutFileName);
    return BT_STATUS_HAL_FS_SUCCESS;

END:
    i = 0;
    pOutFileName[0] = '\0';
    kprintf("*****TIFsRootReadNextDir End OK*****\n");
    return BT_STATUS_HAL_FS_ERROR_INVALID_DIRECTORY_HANDLE_VALUE;

}

int TICommandFsReadNextDir( int dirDesc, char *pOutFileName )
{
    DD *pDd = (DD *)dirDesc;
    if(DD_MAGIC != (0xFFFFFFF0L&pDd->magic)){
        kprintf("Invalid dd\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID_DIRECTORY_HANDLE_VALUE;
    }

    if(NULL == pOutFileName)
    {
        kprintf("TICommandFsReadNextDir invalid argument\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID;
    }

    if(DD_MAGIC_TI_ROOT == pDd->magic){
        return TIFsRootReadNextDir(pOutFileName);
    }

    ECode ec;
    if(NULL == pDd->pIWStringEnumerator){
        ec = pDd->pIBsDirectory->GetDirEntries(&pDd->pIWStringEnumerator);
        if(FAILED(ec)){
            kprintf("FAILED TICommandFsReadNextDir GetDirEntries.ec = 0x%08x\n", ec);
            return BT_STATUS_HAL_FS_ERROR_GENERAL;
        }
        pDd->pIWStringEnumerator->Reset();
    }

    Boolean succeeded;
    while(1){
        pDd->pIWStringEnumerator->MoveNext(&succeeded);
        if(!succeeded){
            pOutFileName[0] = '\0';
            pDd->pIWStringEnumerator->Reset();
        kprintf("*****TICommandFsReadNextDir End OK*****\n");
            return BT_STATUS_HAL_FS_ERROR_INVALID_DIRECTORY_HANDLE_VALUE;
        } else {
            WStringBuf *wscbuf = WStringBuf::Alloc(_MAX_PATH+1);
            ec = pDd->pIWStringEnumerator->Current(wscbuf);
            if(FAILED(ec)){
                kprintf("FAILED TICommandFsReadNextDir Current.ec:0x%x\n", ec);
                WStringBuf:: Free(wscbuf);
                return BT_STATUS_HAL_FS_ERROR_GENERAL;
            }
            //Mask the directory "." & "..".
            if(L'.' == *(wchar_t *)wscbuf->GetPayload()){
                WStringBuf:: Free(wscbuf);
                continue;
            }

            char szRootDir[15];
            if(0 == pDd->iLocation){
                strcpy(szRootDir, FLASH_ROOT);
            } else if(1 == pDd->iLocation){
                strcpy(szRootDir, TF_ROOT);
            }

            strcpy(pOutFileName,szRootDir);
            strcat(pOutFileName, "/");

            wchar_t *tempOutFileName = (wchar_t*)malloc((_MAX_PATH + 1) * 2);

            if (NULL == tempOutFileName)
            {
                kprintf("FAILED malloc tempOutFileName\n", ec);
                WStringBuf:: Free(wscbuf);
                return BT_STATUS_HAL_FS_ERROR_GENERAL;
            }

            memset(tempOutFileName, 0, ((_MAX_PATH + 1) * 2));

            //BUGBUG:May write over the "pOutFileName" buffer
            if(NULL == pDd->wszDirName){
                wcscat(tempOutFileName,wscbuf->GetPayload());
            } else {
                wcscat(tempOutFileName,pDd->wszDirName);
                wcscat(tempOutFileName, L"/");
                wcscat(tempOutFileName,wscbuf->GetPayload());
            }

            if (!UnicodeToutf8(tempOutFileName, (pOutFileName + strlen(pOutFileName))))
            {
                kprintf("UnicodeToutf8 FAILED\n");
                WStringBuf:: Free(wscbuf);
                free(tempOutFileName);
                return BT_STATUS_HAL_FS_ERROR_GENERAL;
            }

            WStringBuf:: Free(wscbuf);
            free(tempOutFileName);
            break;
        }
    }
    kprintf("********TICommandFsReadNextDir****pOutFileName:%s****\n",pOutFileName);

    kprintf("*****TICommandFsReadNextDir OK*****\n");

    return BT_STATUS_HAL_FS_SUCCESS;
}

int TICommandFsCloseDir( int dirDesc )
{
    DD *pDd = (DD *)dirDesc;

    if(DD_MAGIC != (0xFFFFFFF0L&pDd->magic)){
        kprintf("Invalid dd\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID_DIRECTORY_HANDLE_VALUE;
    }

    if(DD_MAGIC_TI_ROOT == pDd->magic){
        return BT_STATUS_HAL_FS_SUCCESS;
    }

    if(NULL != pDd->wszDirName)free(pDd->wszDirName);
    if(NULL != pDd->pIWStringEnumerator)pDd->pIWStringEnumerator->Release();
    if((NULL != pDd->pIBsDirectory)&&(DD_MAGIC_ROOT != pDd->magic)) {
        pDd->pIBsDirectory->Release();
    }
    free(pDd);
    kprintf("*****TICommandFsCloseDir OK*****\n");

    return BT_STATUS_HAL_FS_SUCCESS;
}

int TICommandFsRename(char *szInfullPathOldName, char *szInfullPathNewName )
{

    char* fullPathOldName;
    char* fullPathNewName;
    IBasicDirectory *pIBsDirectory = NULL;

    if((NULL == szInfullPathOldName)
        ||(_MAX_PATH <= strlen(szInfullPathOldName))
        ||(NULL == szInfullPathNewName)
        ||(_MAX_PATH <= strlen(szInfullPathNewName))
        ||('\0' == szInfullPathOldName[0])
        ||('\0' == szInfullPathNewName[0]))
    {
        kprintf("TICommandFsOpenDir invalid argument\n");
        return BT_STATUS_HAL_FS_ERROR_INVALID;
    }

    fullPathOldName = GetRoot(szInfullPathOldName,
        &pIBsDirectory,
        NULL,
        NULL);
    if(NULL == fullPathOldName){
        return BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
    }

    fullPathNewName = GetRoot(szInfullPathNewName,
        NULL,
        NULL,
        NULL);
    if(NULL == fullPathNewName){
        return BT_STATUS_HAL_FS_ERROR_ACCESS_DENIED;
    }

    wchar_t *wszOldFullPath = (wchar_t *)malloc((_MAX_PATH+1)*2);
    if(NULL == wszOldFullPath){
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }
    wchar_t *wszNewFullPath = (wchar_t *)malloc((_MAX_PATH+1)*2);
    if(NULL == wszNewFullPath){
        free(wszOldFullPath);
        return BT_STATUS_HAL_FS_ERROR_OUT_OF_SPACE;
    }
    if (!utf8ToUnicode(fullPathOldName,wszOldFullPath))
    {
        if(NULL != wszOldFullPath)
        {
            free(wszOldFullPath);
        }

        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }

    if (!utf8ToUnicode(fullPathNewName,wszNewFullPath))
    {
        if(NULL != wszNewFullPath)
        {
            free(wszNewFullPath);
        }

        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }


    ECode ec = pIBsDirectory->Rename(wszOldFullPath,
                                       pIBsDirectory,
                                       wszNewFullPath);
    free(wszOldFullPath);
    free(wszNewFullPath);
    if(FAILED(ec)){
        kprintf("FAILED TICommandFsRename Rename.ec = 0x%08x\n", ec);
        return BT_STATUS_HAL_FS_ERROR_GENERAL;
    }
    kprintf("*****TICommandFsRename OK*****\n");
    return BT_STATUS_HAL_FS_SUCCESS;
}

EXTERN_C void FS_TEST()
{
    kprintf("************FS_TEST In************\n");
    int ret;
//    char
    ret = TICommandFsInit();
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsInit************\n");

    ret = TICommandFsMkdir("sub1");
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsMkdir sub1************\n");

    ret = TICommandFsMkdir("sub2");
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsMkdir sub2************\n");

    ret = TICommandFsMkdir("sub3");
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsMkdir sub3************\n");

    ret = TICommandFsRename("sub1", "sub0");
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsRename sub1 -> sub0 ************\n");

    ret = TICommandFsRmdir("sub3");
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsRmdir d:/sub3 ************\n");


    ret = TICommandFsMkdir("sub0/1");
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsMkdir sub0/1************\n");
    ret = TICommandFsMkdir("sub0/2");
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsMkdir sub0/2************\n");
    ret = TICommandFsMkdir("sub0/3");
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsMkdir sub0/3************\n");

    int dirDesc;
    ret = TICommandFsOpenDir("sub0", &dirDesc);
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsOpenDir sub0************\n");

    char ReadData[_MAX_PATH+1];
    memset(ReadData, 0, _MAX_PATH);
    do{
        ret = TICommandFsReadNextDir(dirDesc, ReadData);
        kprintf("Dir Name:%s.\n", ReadData);
    }while('\0' != ReadData[0]);
    kprintf("************FS_TEST TICommandFsReadNextDir sub0************\n");

    ret = TICommandFsCloseDir(dirDesc);
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsCloseDir sub0************\n");


//    enum FileAccessMode {
//        FileAccessMode_Read,
//        FileAccessMode_Write,
//        FileAccessMode_ReadWrite
////    }
////
//#define BT_FS_O_WRONLY   0x00000001      /* write only */
//#define BT_FS_O_CREATE   0x00000002      /* create only */
//#define BT_FS_O_TRUNC    0x00000004      /* if file already exists and it is opened for writing, its length is truncated to zero. */
//#define BT_FS_O_APPEND   0x00000008     /* append to EOF */
//#define BT_FS_O_RDONLY   0x00000010      /* read only */
//#define BT_FS_O_RDWR     0x00000020     /* read & write */
//#define BT_FS_O_EXCL     0x00000040      /* generate error if BT_FS_O_CREATE is also specified and the file already exists.*/
//#define BT_FS_O_BINARY   0x00000080      /* binary file */
//#define BT_FS_O_TEXT     0x00000100      /* text file */

    //File operation test
    int fd;
    ret = TICommandFsOpen("sub2/f2.txt",
        BT_FS_O_CREATE|BT_FS_O_RDWR|BT_FS_O_TEXT|BT_FS_O_EXCL,
        &fd);
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsOpen sub2/f2.txt************\n");

    TICommandFsClose(fd);
    kprintf("************FS_TEST TICommandFsClose sub2/f2.txt************\n");

    ret = TICommandFsRemove("sub2/f2.txt");
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsRemove sub2/f2.txt************\n");

    ret = TICommandFsOpen("sub2/f1.txt",
        BT_FS_O_CREATE|BT_FS_O_RDWR|BT_FS_O_TEXT|BT_FS_O_TRUNC,
        &fd);
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsOpen sub2/f1.txt************\n");

    ret = TICommandFsWrite(fd, (void *)"sub2/f1.txt", 14, NULL);
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsWrite sub2/f1.txt************\n");

    TICommandFsFlush(fd);
    ret = TICommandFsFlush(fd);
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsFlush sub2/f1.txt************\n");

    unsigned int curPosition;
    ret = TICommandFsTell(fd, &curPosition );
    if(ret){
        return;
    }
    kprintf("TICommandFsTell:%d.\n", curPosition);
    kprintf("************FS_TEST TICommandFsTell sub2/f1.txt************\n");

    ret = TICommandFsSeek(fd, 0, BT_FS_START);
    if(ret){
        return;
    }
    kprintf("************FS_TEST TICommandFsSeek sub2/f1.txt************\n");

    unsigned int nReadedSize;
    memset(ReadData, 0, _MAX_PATH);
    ret = TICommandFsRead(fd, ReadData, 20, &nReadedSize);
    if(ret){
        return;
    }
    kprintf("Read file data:%s.length:%d.\n", ReadData, nReadedSize);
    kprintf("************FS_TEST TICommandFsRead sub2/f1.txt************\n");

    BTFsStat FileStat;
    ret = TICommandFsStat("sub2/f1.txt", &FileStat);
    if(ret){
        return;
    }
    kprintf("FileStat.type:%d.\n", FileStat.type);
    kprintf("FileStat.size:%d.\n", FileStat.size);
    kprintf("FileStat.access:%d.\n", FileStat.access);
    kprintf("************FS_TEST TICommandFsStat sub2/f1.txt************\n");

    TICommandFsClose(fd);
    kprintf("************FS_TEST TICommandFsClose sub2/f1.txt************\n");

    TICommandFsDeInit();
    kprintf("************FS_TEST OK************\n");
}

